package com.bamboo.pistorage.factory;

import com.bamboo.model.enums.COSBucketEnum;
import com.bamboo.pistorage.domain.TmpAuthEntity;
import com.bamboo.pistorage.util.CosStsUtil;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.AnonymousCOSCredentials;
import com.qcloud.cos.auth.BasicSessionCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.endpoint.UserSpecifiedEndpointBuilder;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.region.Region;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class TencentCOSClientFactory extends AbstractCOSClientFactory<COSClient>{
    // 使用ConcurrentHashMap保证map操作的线程安全
    private static final Map<COSBucketEnum, COSClient> cosClientMap = new ConcurrentHashMap<>();
    private static final Map<COSBucketEnum, COSClient> anonymousCosClientMap = new ConcurrentHashMap<>();

    /**
     * 获取认证客户端实例（线程安全）
     * @param bucketEnum 存储桶枚举
     * @return COSClient实例
     */
    @Override
    public COSClient getCOSClient(COSBucketEnum bucketEnum) {
        // 首先无锁快速检查
        COSClient client = cosClientMap.get(bucketEnum);
        if (client != null) {
            return client;
        }
        // 如果不存在则进入初始化流程
        return initClient(bucketEnum);
    }

    /**
     * 获取匿名客户端实例（线程安全）
     * @param bucketEnum 存储桶枚举
     * @return COSClient实例
     */
    @Override
    public COSClient getAnonymousCOSClient(COSBucketEnum bucketEnum) {
        COSClient client = anonymousCosClientMap.get(bucketEnum);
        if (client != null) {
            return client;
        }
        return initAnonymousClient(bucketEnum);
    }

    /**
     * 初始化认证客户端（同步方法保证线程安全）
     */
    private synchronized COSClient initClient(COSBucketEnum bucketEnum) {
        // 双重检查防止重复创建
        COSClient client = cosClientMap.get(bucketEnum);
        if (client != null) {
            return client;
        }
        client = createCOSClient(bucketEnum);
        cosClientMap.put(bucketEnum, client);
        return client;
    }

    /**
     * 初始化匿名客户端（同步方法保证线程安全）
     */
    private synchronized COSClient initAnonymousClient(COSBucketEnum bucketEnum) {
        COSClient client = anonymousCosClientMap.get(bucketEnum);
        if (client != null) {
            return client;
        }
        client = createAnonymousCOSClient(bucketEnum);
        anonymousCosClientMap.put(bucketEnum, client);
        return client;
    }

    /**
     * 创建COSClient实例（非线程安全，由同步方法调用）
        // 配置客户端参数
        // 创建凭证对象
        // 获取临时凭证
     */
    private  COSClient createCOSClient(COSBucketEnum bucketEnum) {
        TmpAuthEntity tmpAuth = CosStsUtil.reqTmpAuth(bucketEnum);
        BasicSessionCredentials cred = new BasicSessionCredentials(
            tmpAuth.getSecretId(),
            tmpAuth.getSecretKey(),
            tmpAuth.getToken()
        );
        ClientConfig clientConfig = new ClientConfig(new Region(bucketEnum.getRegion()));
        return new COSClient(cred, clientConfig);
    }

    /**
     * @description 创建匿名客户端
     * @date 2025/3/27 下午1:42
     * @author chenzh
     * @param bucketEnum 存储桶枚举
     * @return COSClient
     */
    private  COSClient createAnonymousCOSClient(COSBucketEnum bucketEnum) {
        // 不需要验证身份信息
        COSCredentials cred = new AnonymousCOSCredentials();
        // ClientConfig 中包含了后续请求 COS 的客户端设置：
        ClientConfig clientConfig = new ClientConfig();
        // 设置 bucket 的地域
        // COS_REGION 请参照 https://cloud.tencent.com/document/product/436/6224
        clientConfig.setRegion(new Region(bucketEnum.getRegion()));
        // 设置生成的 url 的请求协议, http 或者 https
        // 5.6.53 及更低的版本，建议设置使用 https 协议
        // 5.6.54 及更高版本，默认使用了 https
        clientConfig.setHttpProtocol(HttpProtocol.https);
        // 设置自定义的域名
        UserSpecifiedEndpointBuilder endpointBuilder = new UserSpecifiedEndpointBuilder(
                bucketEnum.getCustomDomain(), bucketEnum.getCosDomain()
        );
        clientConfig.setEndpointBuilder(endpointBuilder);
        // 生成 cos 客户端。
        return new COSClient(cred, clientConfig);
    }

    /**
     * 销毁所有客户端实例
     */
    public  synchronized void shutdown() {
        cosClientMap.values().forEach(COSClient::shutdown);
        anonymousCosClientMap.values().forEach(COSClient::shutdown);
        cosClientMap.clear();
        anonymousCosClientMap.clear();
    }
}
